package com.fc.redap.helper;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class ClassUtils {
    private static final Map<Class<?>, Class<?>> primitiveMap = new HashMap<>(9);

    static {
        primitiveMap.put(String.class, String.class);
        primitiveMap.put(Boolean.class, boolean.class);
        primitiveMap.put(Byte.class, byte.class);
        primitiveMap.put(Character.class, char.class);
        primitiveMap.put(Double.class, double.class);
        primitiveMap.put(Float.class, float.class);
        primitiveMap.put(Integer.class, int.class);
        primitiveMap.put(Long.class, long.class);
        primitiveMap.put(Short.class, short.class);
        primitiveMap.put(Date.class, Date.class);
        primitiveMap.put(BigDecimal.class, BigDecimal.class);
    }

    /**
     * 判断基本类型
     * @see     Boolean#TYPE
     * @see     Character#TYPE
     * @see     Byte#TYPE
     * @see     Short#TYPE
     * @see     Integer#TYPE
     * @see     Long#TYPE
     * @see     Float#TYPE
     * @see     Double#TYPE
     * @see     Boolean#TYPE
     * @param clazz @description class
     * @return isPrimitive boolean
     */
    public static boolean isPrimitive(Class<?> clazz) {
        if (primitiveMap.containsKey(clazz)) {
            return true;
        }
        return clazz.isPrimitive();
    }

    /**
     * 获取方法返回值类型
     * @param target @description target
     * @param fieldName @description fieldName
     * @return Class<?>
     */
    public static Class<?> getElementType(Class<?> target, String fieldName) {
        Class<?> elementTypeClass;
        try {
            Field field = getField(target, fieldName);
            if(field == null){
                return null;
            }
            Type type = field.getGenericType();
            ParameterizedType t = (ParameterizedType) type;
            String classStr = t.getActualTypeArguments()[0].toString().replace("class ", "");
            elementTypeClass = Thread.currentThread().getContextClassLoader().loadClass(classStr);
        } catch (ClassNotFoundException | SecurityException e) {
            throw new RuntimeException("get fieldName[" + fieldName + "] error", e);
        }
        return elementTypeClass;
    }

    public static Field getField(Class<?> target, String fieldName){
        Field field = null;
        Class<?> clazz = target ;
        for(; clazz != Object.class ; clazz = clazz.getSuperclass()) {
            try {
                field = clazz.getDeclaredField(fieldName);
                return field;
            } catch (Exception e) {
                //这里甚么都不要做！并且这里的异常必须这样写，不能抛出去。
                //如果这里的异常打印或者往外抛，则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }
        return field;
    }
}
